<template>
    <div class="file-upload">
        <!-- slot传值 :item='item' -->
        <!-- 引用的组件  v-slot:default='slotProps' slotProps.item-->
        <div class="file-upload-container" @click.prevent="triggerUpload" v-bind="attrs">
            <slot v-if="fileStatus==='loading'" name="loading">
                <button class="btn btn-primary" disabled>正在上传...</button>
            </slot>
            <slot v-else-if="fileStatus==='sucess'" name="uploaded" :uploadedData="uploadedData">
                <button class="btn btn-primary">上传成功</button>
            </slot>
            <slot v-else name="default">
                <button class="btn btn-primary">点击上传</button>
            </slot>
        </div>
        
        <input type="file" class="file-input d-none" ref="fileInput" @change="handleFileChange"/>
    </div>
</template>
<script lang="ts">
import axios from 'axios'
import {defineComponent, PropType, ref,watch} from 'vue'
type UploadStatus='ready'|'loading'|'success'|'error'
type CheckFunction=(file:File)=>boolean
export default defineComponent({
    name:'UploaderPage',
    props:{
        action:{
            type:String,
            required:true
        },
        beforeUpload:{
            type:Function as PropType<CheckFunction>
        },
        uploaded:{
            type:Object
        }
    },
    inheritAttrs:false,
    emits:['file-uploaded','file-uploaded-error'],
    setup(props,context){
        // 获取到了input这个dom
        const fileInput=ref<null|HTMLInputElement>(null)
        const fileStatus = ref<UploadStatus>(props.uploaded ? 'success' : 'ready')
        const uploadedData = ref(props.uploaded)
        // 因为props.uploaded不是响应式数据，所以要用()=>props.uploaded
        watch(()=>props.uploaded,(newValue)=>{
            if(newValue){
                fileStatus.value='success'
                uploadedData.value=newValue
            }
        })
        const triggerUpload=()=>{
            if(fileInput.value){
                fileInput.value.click()
            }
        }
        const handleFileChange=(e:Event)=>{
            const currentTarget=e.target as HTMLInputElement
            if(currentTarget.files){
                fileStatus.value='loading'
                const files=Array.from(currentTarget.files)
                //校验图片的格式是否符合要求
                if(props.beforeUpload){
                    const result=props.beforeUpload(files[0])
                    if(!result){return}
                }
                const formData=new FormData()
                formData.append('file',files[0])
                axios.post(props.action,formData,{
                    headers:{'Content-Type':'multipart/form-data'}
                }).then(resp=>{
                    console.log(resp.data)
                    fileStatus.value='success'
                    uploadedData.value=resp.data
                    context.emit('file-uploaded',resp.data)
                }).catch((error)=>{
                    fileStatus.value='error'
                    context.emit('file-uploaded-error',{ error })
                }).finally(()=>{
                    if(fileInput.value){
                        // 重置input的值
                        fileInput.value.value=''
                    }
                })
            }
        }
        return {
            fileInput,
            fileStatus,
            uploadedData,
            triggerUpload
        }
    }
    
})
</script>